use std::collections::HashMap;
use std::sync::{Arc, Mutex};
use chrono::Duration;
use lazy_static::lazy_static;

static DefaultTimeout:i64 = 1000;
static DefaultMaxConcurrent:i64 = 10;
static DefaultVolumeThreshold:i64 = 20;
static DefaultSleepWindow:i64 = 5000;
static DefaultErrorPercentThreshold:i64 = 50;


pub struct CircuitSettings{
    inner:Arc<Mutex<HashMap<String,Settings>>>
}

impl CircuitSettings {
    pub fn new() -> Self {
        CircuitSettings{
            inner:Arc::new(Mutex::new(HashMap::new())),
        }
    }
}

impl CircuitSettings {
    pub fn get_settings(&mut self,name:String) -> Settings {
        let borrow = self.inner.lock().unwrap().clone();
        let res = borrow.get(name.as_str());
        match res {
            None=> {
                self.configure_command(name.clone(),None);
                return self.get_settings(name);
            },
            Some(d) => {
                return d.clone();
            }
        }
    }

    pub fn configure_command(&mut self,name:String,config:Option<CommandConfig>) {
        let mut timeout = DefaultTimeout;
        let mut max = DefaultMaxConcurrent;
        let mut volume = DefaultVolumeThreshold;
        let mut sleep = DefaultSleepWindow;
        let mut errorPercent = DefaultErrorPercentThreshold;

        if let Some(c) = config {
            timeout = c.timeout;
            max = c.timeout;
            volume = c.request_volume_threshold;
            sleep = c.sleep_window;
            errorPercent = c.error_percent_threshold;
        }

        self.inner.lock().unwrap().insert(name,Settings{
            time_out: Duration::milliseconds(timeout),
            max_concurrent_requests: max,
            request_volume_threshold: volume as u64,
            sleep_window: Duration::milliseconds(sleep),
            error_percent_threshold: errorPercent
        });
    }

    pub fn configure(&mut self, cmd:HashMap<String,CommandConfig>) {
        for (k,v) in cmd {
            self.configure_command(k,Some(v))
        }
    }
}


#[derive(Clone)]
pub struct Settings {
    time_out:Duration,
    max_concurrent_requests:i64,
    request_volume_threshold:u64,
    sleep_window:Duration,
    error_percent_threshold:i64,
}


pub struct CommandConfig {
    timeout:i64,
    max_concurrent_requests:i64,
    request_volume_threshold:i64,
    sleep_window:i64,
    error_percent_threshold:i64,
}

#[cfg(test)]
mod test {
    use crate::hystrix::settings::CircuitSettings;

    #[test]
    fn test() {
        let mut stting = CircuitSettings::new();

    }
}